/**
 * 日志服务
 * 提供统一的日志记录机制，支持不同级别的日志输出、格式化和存储
 */

// 日志级别枚举
export const LogLevel = {
  DEBUG: 'debug',
  INFO: 'info',
  WARNING: 'warning',
  ERROR: 'error',
  CRITICAL: 'critical',
  NONE: 'none'
};

/**
 * JSON格式化器
 */
class JsonFormatter {
  format(log) {
    return JSON.stringify(log);
  }
}

/**
 * 文本格式化器
 */
class TextFormatter {
  format(log) {
    let result = `[${log.timestamp}] [${log.level.toUpperCase()}] ${log.message}`;
    
    if (log.context && Object.keys(log.context).length > 0) {
      result += `\nContext: ${JSON.stringify(log.context, null, 2)}`;
    }
    
    if (log.error) {
      result += `\nError: ${JSON.stringify(log.error, null, 2)}`;
    }
    
    if (log.meta && Object.keys(log.meta).length > 0) {
      result += `\nMeta: ${JSON.stringify(log.meta, null, 2)}`;
    }
    
    return result;
  }
}

/**
 * 控制台格式化器
 */
class ConsoleFormatter {
  format(log) {
    // 这个格式化器主要用于console输出，返回的是可用于console方法的参数数组
    const timestamp = new Date(log.timestamp).toLocaleString();
    return `[${timestamp}] [${log.level.toUpperCase()}] ${log.message}`;
  }
  
  getConsoleArgs(log) {
    const formattedMessage = this.format(log);
    const args = [formattedMessage];
    
    if (log.context && Object.keys(log.context).length > 0) {
      args.push('Context:', log.context);
    }
    
    if (log.error) {
      args.push('Error:', log.error);
    }
    
    if (log.meta && Object.keys(log.meta).length > 0) {
      args.push('Meta:', log.meta);
    }
    
    return args;
  }
}

/**
 * 内存存储
 */
class MemoryStorage {
  constructor(maxSize = 1000) {
    this._logs = [];
    this._maxSize = maxSize;
  }
  
  save(log) {
    if (this._logs.length >= this._maxSize) {
      this._logs.shift();
    }
    this._logs.push(log);
  }
  
  getLogs() {
    return [...this._logs];
  }
  
  clear() {
    this._logs = [];
  }
}

/**
 * 本地存储
 */
class LocalStorage {
  constructor(key = 'lifeservice_logs', maxSize = 500) {
    this._key = key;
    this._maxSize = maxSize;
  }
  
  save(log) {
    try {
      const logs = this.getLogs();
      if (logs.length >= this._maxSize) {
        logs.shift();
      }
      logs.push(log);
      localStorage.setItem(this._key, JSON.stringify(logs));
    } catch (error) {
      console.error('Failed to save log to localStorage:', error);
    }
  }
  
  getLogs() {
    try {
      const logs = localStorage.getItem(this._key);
      return logs ? JSON.parse(logs) : [];
    } catch (error) {
      console.error('Failed to get logs from localStorage:', error);
      return [];
    }
  }
  
  clear() {
    try {
      localStorage.removeItem(this._key);
    } catch (error) {
      console.error('Failed to clear logs from localStorage:', error);
    }
  }
}

/**
 * 远程存储
 */
class RemoteStorage {
  constructor(url, options = {}) {
    this._url = url;
    this._bufferSize = options.bufferSize || 20;
    this._flushInterval = options.flushInterval || 5000;
    this._buffer = [];
    this._timeout = null;
    
    // 定期刷新缓冲区
    this._startAutoFlush();
  }
  
  save(log) {
    this._buffer.push(log);
    
    // 缓冲区达到阈值时立即发送
    if (this._buffer.length >= this._bufferSize) {
      this._flush();
    }
  }
  
  _flush() {
    if (this._buffer.length === 0) return;
    
    const logsToSend = [...this._buffer];
    this._buffer = [];
    
    fetch(this._url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        logs: logsToSend,
        timestamp: new Date().toISOString(),
        userAgent: navigator.userAgent
      })
    }).catch(error => {
      console.error('Failed to send logs to remote server:', error);
      // 如果发送失败，将日志重新加入缓冲区
      this._buffer = [...logsToSend, ...this._buffer];
    });
  }
  
  _startAutoFlush() {
    this._timeout = window.setInterval(() => {
      this._flush();
    }, this._flushInterval);
  }
  
  stopAutoFlush() {
    if (this._timeout) {
      clearInterval(this._timeout);
      this._timeout = null;
    }
  }
  
  // 手动触发一次发送
  manualFlush() {
    this._flush();
  }
}

/**
 * 日志服务类
 */
class LoggerService {
  constructor(options = {}) {
    this._options = {
      // 默认配置
      level: LogLevel.INFO,
      formatter: 'console',
      enableConsole: true,
      storages: ['memory'],
      storageOptions: {
        memory: { maxSize: 1000 },
        local: { key: 'lifeservice_logs', maxSize: 500 },
        remote: { url: null, bufferSize: 20, flushInterval: 5000 }
      },
      includeTimestamp: true,
      includeContext: true,
      ...options
    };
    
    // 初始化日志级别优先级
    this._levelPriority = new Map([
      [LogLevel.DEBUG, 0],
      [LogLevel.INFO, 1],
      [LogLevel.WARNING, 2],
      [LogLevel.ERROR, 3],
      [LogLevel.CRITICAL, 4],
      [LogLevel.NONE, 5]
    ]);
    
    this._logLevelThreshold = this._levelPriority.get(this._options.level) || 1;
    
    // 初始化格式化器
    this._formatters = new Map([
      ['json', new JsonFormatter()],
      ['text', new TextFormatter()],
      ['console', new ConsoleFormatter()]
    ]);
    
    this._currentFormatter = this._formatters.get(this._options.formatter) || this._formatters.get('console');
    
    // 初始化存储
    this._storages = [];
    this._initializeStorages();
    
    // 上下文数据
    this._context = {};
  }
  
  /**
   * 初始化存储
   */
  _initializeStorages() {
    const storageTypes = Array.isArray(this._options.storages) 
      ? this._options.storages 
      : [this._options.storages];
    
    storageTypes.forEach(type => {
      switch (type) {
        case 'memory':
          this._storages.push(new MemoryStorage(this._options.storageOptions.memory?.maxSize));
          break;
        case 'local':
          if (typeof localStorage !== 'undefined') {
            this._storages.push(new LocalStorage(
              this._options.storageOptions.local?.key,
              this._options.storageOptions.local?.maxSize
            ));
          }
          break;
        case 'remote':
          if (this._options.storageOptions.remote?.url) {
            this._storages.push(new RemoteStorage(
              this._options.storageOptions.remote.url,
              {
                bufferSize: this._options.storageOptions.remote.bufferSize,
                flushInterval: this._options.storageOptions.remote.flushInterval
              }
            ));
          }
          break;
      }
    });
  }
  
  /**
   * 检查日志级别是否应该输出
   */
  _shouldLog(level) {
    const levelPriority = this._levelPriority.get(level);
    return levelPriority !== undefined && levelPriority >= this._logLevelThreshold;
  }
  
  /**
   * 创建日志数据
   */
  _createLogData(level, message, data = {}) {
    const logData = {
      timestamp: new Date().toISOString(),
      level,
      message
    };
    
    // 添加上下文
    if (this._options.includeContext && Object.keys(this._context).length > 0) {
      logData.context = { ...this._context };
    }
    
    // 处理错误对象
    if (data.error) {
      logData.error = {
        message: data.error.message,
        stack: data.error.stack,
        code: data.error.code,
        type: data.error.type,
        ...data.error
      };
      delete logData.error.stack;
      delete logData.error.message;
    }
    
    // 添加额外元数据
    if (data.meta) {
      logData.meta = data.meta;
    }
    
    return logData;
  }
  
  /**
   * 记录日志
   */
  log(data) {
    const logData = data instanceof Object && 'level' in data && 'message' in data
      ? this._createLogData(data.level, data.message, data)
      : data;
    
    if (!this._shouldLog(logData.level)) return;
    
    // 格式化日志
    const formattedLog = this._currentFormatter.format(logData);
    
    // 输出到控制台
    if (this._options.enableConsole) {
      this._logToConsole(logData);
    }
    
    // 保存到存储
    this._storages.forEach(storage => {
      try {
        storage.save(formattedLog);
      } catch (error) {
        console.error('Failed to save log to storage:', error);
      }
    });
  }
  
  /**
   * 输出到控制台
   */
  _logToConsole(logData) {
    const consoleFormatter = this._formatters.get('console');
    const args = consoleFormatter.getConsoleArgs(logData);
    
    switch (logData.level) {
      case LogLevel.DEBUG:
        console.debug(...args);
        break;
      case LogLevel.INFO:
        console.info(...args);
        break;
      case LogLevel.WARNING:
        console.warn(...args);
        break;
      case LogLevel.ERROR:
      case LogLevel.CRITICAL:
        console.error(...args);
        break;
      default:
        console.log(...args);
    }
  }
  
  /**
   * 记录调试日志
   */
  debug(message, data = {}) {
    this.log({
      level: LogLevel.DEBUG,
      message,
      ...data
    });
  }
  
  /**
   * 记录信息日志
   */
  info(message, data = {}) {
    this.log({
      level: LogLevel.INFO,
      message,
      ...data
    });
  }
  
  /**
   * 记录警告日志
   */
  warning(message, data = {}) {
    this.log({
      level: LogLevel.WARNING,
      message,
      ...data
    });
  }
  
  /**
   * 记录错误日志
   */
  error(message, data = {}) {
    this.log({
      level: LogLevel.ERROR,
      message,
      ...data
    });
  }
  
  /**
   * 记录严重错误日志
   */
  critical(message, data = {}) {
    this.log({
      level: LogLevel.CRITICAL,
      message,
      ...data
    });
  }
  
  /**
   * 设置日志级别
   */
  setLevel(level) {
    if (this._levelPriority.has(level)) {
      this._options.level = level;
      this._logLevelThreshold = this._levelPriority.get(level) || 1;
    }
  }
  
  /**
   * 获取日志级别
   */
  getLevel() {
    return this._options.level;
  }
  
  /**
   * 设置上下文数据
   */
  setContext(context) {
    this._context = { ...this._context, ...context };
  }
  
  /**
   * 获取上下文数据
   */
  getContext() {
    return { ...this._context };
  }
  
  /**
   * 清除上下文数据
   */
  clearContext() {
    this._context = {};
  }
  
  /**
   * 添加存储
   */
  addStorage(storage) {
    this._storages.push(storage);
  }
  
  /**
   * 移除所有存储
   */
  clearStorages() {
    this._storages.forEach(storage => {
      if (typeof storage.clear === 'function') {
        storage.clear();
      }
    });
    this._storages = [];
  }
  
  /**
   * 手动刷新远程日志
   */
  flushLogs() {
    this._storages.forEach(storage => {
      if (storage instanceof RemoteStorage) {
        storage.manualFlush();
      }
    });
  }
  
  /**
   * 初始化服务
   */
  async boot() {
    // 记录服务启动信息
    this.info('LoggerService booted', {
      level: this._options.level,
      storages: this._options.storages
    });
    
    return this;
  }
}

export default LoggerService;